/*========================================================================
#include <stdio.h>
#   FileName: manage.c
#     Author: lwd
#      Email: lwd_xinghuo@126.com
#   HomePage: 
# LastChange: 2013-04-18 09:56:32
========================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>
#include "Process.h"
#include "control.h"
#include "prosync.h"
#include "config.h"

#if 1
#define PRINT_FUNC() \
	do{\
		printf("file:%s func:%s LINE:%d \n",\
				__FILE__, __func__, __LINE__);\
	}while(0)
#else
#define PRINT_FUNC() do{}while(0)
#endif
//time slice
#define TIME_SLICE 3

//控制manage线程中，计时器与信号处理的同步
static pthread_mutex_t pthm = PTHREAD_MUTEX_INITIALIZER;
//控制测试任务的互斥
static pthread_mutex_t smtm = PTHREAD_MUTEX_INITIALIZER;
//控制当前是否可以中断某任务
static pthread_mutex_t sttm = PTHREAD_MUTEX_INITIALIZER;

static void weakup(int sig_num)
{
	PRINT_FUNC();
	pthread_mutex_lock(&smtm);
	pthread_mutex_lock(&sttm);
	stop();
	pthread_mutex_unlock(&pthm);
}

static void finished(int sig_num)
{
	PRINT_FUNC();
	//在计时到此可以转为测试任务
	//此处之后，再次转为不可转换为测试任务
	pthread_mutex_lock(&smtm);
	pthread_mutex_lock(&sttm);
	alarm(0);
#if 1
	//while there is a process is finished,
	//this function responding
	int r = releaseChild();
	printf("child %d is finished! func:%s LINE:%d\n",
		   	r, __func__, __LINE__);
	pthread_mutex_unlock(&pthm);
	//exit (0);
#endif
}

static void testfinish(int sig_num)
{
}

static void timer(int sec)
{
	//timer: retrun after sec seconds
	//在函数开始，先run当前选中的进程，
	//计时结束后，在weakup函数中调用stop暂停当前选中函数
	PRINT_FUNC();
	signal(SIGALRM, weakup);
	signal(SIGCHLD, finished);
	run();
	alarm(sec);
	//解锁，允许执行销毁任务操作
	pthread_mutex_unlock(&sttm);
	//解锁，在线程进入计时过程，允许转为测试任务
	//直到计时结束，或者当前任务结束
	pthread_mutex_unlock(&smtm);
	//线程锁，等待计时结束或者当前进程完成
	pthread_mutex_lock(&pthm);
	printf("time over!\n");
}

static int pauseCurrentProcess()
{
	int ret = 0;
	ret = alarm(0);
	int r = pauseCurrent();
	//printf("pauseCurrent ret = %d\n", r);
	return ret;
}

static int continueCurrent(int sec)
{
	int ret = 1;
	if(sec > 0)
	{
		alarm(sec);
		ret = run();
	}
	return ret;
}

static int IntToStr(int num, char str[])
{
	int i = 0, j = 0;
	char temp[16];
	while(num)
	{
		temp[i] = num % 10 + '0';
		num = num / 10;
		i++;
	}
	temp[i] = '\0';
	i--;
	while(i >= 0)
	{
		str[j] = temp[i];
		i--;
		j++;
	}
	str[j] = '\0';
	return 0;
}

static int testProcesss(char* modeName, char* modeFile, \
		char* dataFile, int steplen, char* rsfile)
{
	//PRINT_FUNC();
	//创建测试进程
	pid_t pid = fork();
	//printf("modemame = %s\n", modeName);
	if(pid == 0)
	{
		//PRINT_FUNC();
		//子进程，调用测试程序（execv），转变为测试进程
		printf("create a test process! pid = %d\n", getpid());
		char modelpath[MAXFILENAMESIZE] = "./data/";
		char datapath[MAXFILENAMESIZE]  = "./data/";
		char rsltpath[MAXFILENAMESIZE]  = "./result/";
		strcat(modelpath, modeFile);
		strcat(datapath,  dataFile);
		strcat(rsltpath, rsfile);
		PRINT_FUNC();
		char steplength[16];
		bzero(steplength, 16);
		IntToStr(steplen, steplength);
		PRINT_FUNC();
		char* args[] = { modeName, modelpath, datapath,steplength, rsltpath, NULL };
		const Service* s = getServiceInfo(modeName);
		printf("tpath = %s\n", s->tpath);
		return execv(s->tpath, args);
	}
	else if(pid > 0)
	{
		//PRINT_FUNC();
		//修改信号处理函数，等待此子进程结束
		signal(SIGCHLD, testfinish);
		//父进程，等待测试任务完成
		printf("father process!\n");
		//fgetc(stdin);
		waitpid(pid, 0, 0);
		//注意：返回结果文件，在线程中调用此函数处执行
		//改会调度时，子进程结束的信号处理函数
		signal(SIGCHLD, finished);
		return 0;
	}
	else
	{
		return 1;
	}
}


int testModel(char* modelName, char* modelFile, char* dataFile, int steplen, \
			  char* rsfile)
{
	//PRINT_FUNC();
	//阻断其他进程，同时锁住timer函数
	pthread_mutex_lock(&smtm);
	int r;
	//暂停当前进程
	int ret = pauseCurrentProcess();
	//printf("ret = %d\n", ret);
	
	//创建测试模型任务，测试模型
	r = testProcesss(modelName, modelFile, dataFile, steplen, rsfile);
	
	//继续当前进程
	ret = continueCurrent(ret);
	//printf("ret = %d\n", ret);
	//允许其他进程测试，或者继续timer函数
	pthread_mutex_unlock(&smtm);
	return r;
}

int killProcess(int jid)
{
	pthread_mutex_lock(&sttm);
	int ret = deleteFromList(jid);
	printf("deleteFormList ret = %d\n", ret);
	pthread_mutex_unlock(&sttm);
	return ret;
}

#if 1
//
char* ag[5] = { "A", "B", "C", "D", "E" };

static int createProcess(int id)
{
#if 1
	int ret = fork();
	if(ret == 0)
	{
		printf("this is the %dth child process!\n", id);
		char* args[] = { "./gepLinux/main", "./data/canshu.txt" , \
											"./data/shuju.txt",\
											"./temp/temp.txt", \
											"./result/rslt.txt",\
											NULL};
		
		const Service* s = getServiceInfo("path");
		printf("tpath = %s\n", s->tpath);
		
		execv(s->mpath, args);
		//char* args[] = {"./func1", "A", "b", "c" ,"d", NULL};
		//execv("./src/gepLinux/main", args);
		//execv("./src/func1", args);
	}
#endif
	PRINT_FUNC();
	//return id + 1;
	return ret;
}

void *skillPro(void* args)
{
	pthread_detach(pthread_self());
	sleep(3);
	printf("销毁进程！");
	int ret = killProcess(0);
	printf("killProcess ret = %d\n", ret);
}

void *createProcesses(void* arg)
{
	pthread_detach(pthread_self());
	int cpid;
	int i = 0;
	Process p;
	
	printf("this is createProcess function! func:%s line:%d\n", __func__, __LINE__);
	sleep(1);
	for(i = 0; i < 1; i++)
	{
		cpid = createProcess(i);
		if(cpid > 0)
		{
			p.pid = cpid;
			p.jid = i;
			p.state = WAIT;
			strcpy(p.rsltfile, "./123.txt");
			sleep(1);
			add_new(p);
		}
		else
		{
			printf("create child-process failed! func:%s line:%d\n",\
					__func__, __LINE__);
		}
	}
#if 1
	for(i = 0; i < 5; i++)
	{
		p.jid = i;
		search(&p);
		printf("search: pid = %d jid = %d state = %d\n", \
				p.pid, p.jid, p.state);
	}
#endif
#if 1 
	int pid;
	sleep(4);
	printf("\n\ntest Process\n");
	//pthread_t pthr;
	//pthread_create(&pthr, NULL, skillPro, NULL);
	testModel("path", "data.txt", "para.txt", 4, "result.txt");
#endif
	pthread_exit(0);
	//return 0;
}
#endif



void *manage(void* arg)
{
	
	printf("this is manage function! func:%s line:%d\n", __func__, __LINE__);
	
	//pthread lock to implement sync
	//线程锁，此处调用，让资源数记为0，实现同步
	pthread_mutex_lock(&pthm);
	//线程锁，此处调用，让资源为0，
	//实现调度线程与socket通信线程中到测试任务的同步
	//此处到选择当前要执行任务之前，不允许转为测试任务
	pthread_mutex_lock(&smtm);
	//线程锁，此处调用，让资源为0
	//实现销毁任务的的同步
	pthread_mutex_lock(&sttm);
	int i = 0;
	while(1)
	{
		printf("while time %d\n", i++);
		//选择一个任务，如果队列为空，等待
		while(choose()) 
		{
			//解锁，允许销毁任务
			pthread_mutex_unlock(&sttm);
			//解线程锁，允许执行调度任务
			pthread_mutex_unlock(&smtm);
			//
			//解锁与上锁之间 允许 中断线程，执行测试任务
			//防止，当任务队列一直为空时，测试任务一直等待
			//
			//线程锁，在执行choose的同时，不能转为测试任务
			//如果队列不为空，可以得到一个当前任务
			//此处到进入计时之前不允许转为测试任务
			pthread_mutex_lock(&smtm);
			pthread_mutex_lock(&sttm);
		}
		
		timer(TIME_SLICE);
	}
}


